package alp.starcode.nudtportal.framework.aspect;

import alp.starcode.nudtportal.framework.mybatis.dao.impl.LogUserActionDaoImpl;
import alp.starcode.nudtportal.framework.mybatis.entity.LogUserAction;
import alp.starcode.nudtportal.framework.util.RequestHolder;
import alp.starcode.nudtportal.framework.aspect.model.UserActionLog;
import alp.starcode.nudtportal.framework.login.user.User;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;

@Slf4j
@Aspect
@Component
public class UserActionAspect {
    @Autowired
    LogUserActionDaoImpl logUserActionDao;

    @Autowired
    RestHighLevelClient client;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Resource
    RequestHolder requestHolder;

    //切入点为使用了Login注解的任何地方
    @Pointcut("@annotation(alp.starcode.nudtportal.framework.aspect.model.UserActionLog)")
    public void logPointCut() {

    }

    @Before(value = "logPointCut()")
    public void before() {
    }


    @After(value = "logPointCut()")
    public void after() {
    }


    @Around(value = "logPointCut() && @annotation(userActionLog)", argNames = "joinPoint,userActionLog")
    public Object around(ProceedingJoinPoint joinPoint, UserActionLog userActionLog) throws Throwable {
        Object proceed = null;
        LogUserAction logUserAction = new LogUserAction();
        logUserAction.setActionId(UUID.randomUUID().toString());
        User currentLoginCASUser = requestHolder.getCurrentLoginCASUser();
        logUserAction.setUserId(currentLoginCASUser.getUserId());
        logUserAction.setLoginName(currentLoginCASUser.getLoginAccount());
        logUserAction.setCampusNumber(currentLoginCASUser.getCampusNumber());
        logUserAction.setBusinessName(userActionLog.businessName());
        //0-新增，1-修改，2-删除，3-查询
        logUserAction.setAccessType(Integer.valueOf(userActionLog.accessType()));
        // 从请求头中获取用户IP
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        logUserAction.setIpAddress(getIp(request));
        // 获取服务器IP
//        SystemInfo si = new SystemInfo();
//        OperatingSystem os = si.getOperatingSystem();
//        logUserAction.setServerIpAddress(os.getNetworkParams().getHostName());
        logUserAction.setServerIpAddress(request.getLocalAddr());
        // 从请求头中获取操作内容
        logUserAction.setAccessContent(JSONObject.toJSONString(request.getParameterMap()));
        logUserAction.setCreateTime(System.currentTimeMillis());
        logUserAction.setUpdateTime(System.currentTimeMillis());
//        logUserActionDao.save(logUserAction);
        // 小程序用户操作日志存es
        addUserActionLog(logUserAction);
        try {
            proceed = joinPoint.proceed();
        } catch (Exception e) {
            throw e;
        }
        return proceed;
    }

    private String getIp(HttpServletRequest request) {
        /**
         * 获取客户端ip，客户端可能经过代理，也可能没经过代理
         */
        String ip = request.getHeader("x-forwarded-for");
        log.debug("x-forwarded-for ip: " + ip);
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if (ip.indexOf(",") != -1) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            log.debug("Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            log.debug("WL-Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            log.debug("HTTP_CLIENT_IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            log.debug("HTTP_X_FORWARDED_FOR ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
            log.debug("X-Real-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            log.debug("getRemoteAddr ip: " + ip);
        }

        log.debug("----获取客户端的ip: " + ip);
        //如果没取到ip，返回""
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = "";
        }

        return ip;
    }

    private void addUserActionLog(LogUserAction logUserAction)  {
        try {
            elasticsearchRestTemplate.save(logUserAction);
        }catch (Exception e){
            log.error("用户行为日志记录失败{}",e.getMessage());
        }


    }
}
